/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package util.file.xml;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import util.file.CodificacionTexto;

/*
NORMALIZACION
http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work

Sea el siguiente XML
<foo>hello 
wor
ld</foo>

El nodo desnormalizado es:
Element foo
    Text node: ""
    Text node: "Hello "
    Text node: "wor"
    Text node: "ld"
El nodo normalizado es:
Element foo
    Text node: "Hello world"
*/

/*
Ejemplo de como usar la clase Document para crear un XML
http://www.mkyong.com/java/how-to-create-xml-file-in-java-dom/
doc.createTextNode(null) //Lanza NullPointerException
*/

/**
 *
 * @author Rdelacruz
 */
public class ArchivoXml {

    protected final Document document;

    
    public ArchivoXml(String dataXml) 
            throws ParserConfigurationException, 
            SAXException, IOException {
    	this.document = stringToDocument(dataXml);
    }

        
    public ArchivoXml(File fileXml) 
            throws ParserConfigurationException, 
            SAXException, IOException {
        this(fileXml,false);
    }
    
    public ArchivoXml(File fileXml, boolean normalizar) 
            throws ParserConfigurationException, 
            SAXException, IOException {
    	Document doc = fileToDocument(fileXml);
        preProcesarDocument(doc,normalizar);
        this.document = doc;        
    }
    
    public ArchivoXml() throws ParserConfigurationException  {
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = builderFactory.newDocumentBuilder();
        this.document = docBuilder.newDocument();
    }
    
    private void preProcesarDocument(Document doc, boolean normalizar) {
        if(normalizar) {
            //Normalizando todos los nodos del XML
            Element eRaiz = doc.getDocumentElement();
            eRaiz.normalize();
        }
    }
    
    //Xml proviene de un texto
    //http://stackoverflow.com/questions/3888033/how-to-convert-string-to-xml-file-in-java 
    protected Document stringToDocument(String dataXml) 
    		throws ParserConfigurationException, 
            SAXException, IOException  {
    	DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        
        //Lanza SAXException
        return dBuilder.parse(new InputSource(new StringReader(dataXml)));
    }
    
    
    //Xml proviene de un archivo
    //BUG: DocumentBuilder.parse() no cierra el archivo si ocurre una excepcion
    //Sin embargo luego de un tiempo, el sistema cierra el archivo.
    protected Document fileToDocument(File fileXml) 
    		throws ParserConfigurationException, 
    		SAXException, IOException {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        return dBuilder.parse(fileXml);//Lanza SAXException    	
    }
   
    public String getDataXmlCompacta() throws TransformerException {        
        return XmlUtil.documentXmlToStringCompacto(document,null);
    }
    
    public String getDataXml() throws TransformerException {        
        return XmlUtil.documentXmlToString(document,null);
    }    
    
    public String getDataXml(CodificacionTexto codificacion) throws TransformerException {        
        return XmlUtil.documentXmlToString(document,codificacion);
    }
    
    //http://stackoverflow.com/questions/11473805/create-a-xml-file-using-jsp-coding-and-store-in-local-disk-folder
    public void exportar(String ruta) throws IOException, TransformerException {
        //File file=new File("C:xml/"+str+".xml");
        File file=new File(ruta);
        BufferedWriter bw = new BufferedWriter(new FileWriter(file));
        bw.write(getDataXmlCompacta());
        bw.flush();
        bw.close();
    }
        
    public Document getDocument() {
        return document;
    }
    
}
